home *** CD-ROM | disk | FTP | other *** search
/ SoundMaker 2003 (Professional Edition) / SoundMaker 2003 - Professional Edition.iso / midi tool / midioxse.exe / DATA.1 / slowarp.rex < prev    next >
OS/2 REXX Batch file  |  1999-03-27  |  4KB  |  156 lines

  1. /* REXX: Simple MIDI Arpeggiator */
  2. /* This Runs a slow single finger aprepggiator */
  3.  
  4. call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  5. call SysLoadFuncs 
  6.  
  7. qName = MoxGetQueueName()
  8. oldq  = RxQueue( 'Set', qName )
  9.  
  10. /* MIDI-OX creates a semaphore with same name as queue */
  11. sem = SysOpenEventSem( qName )
  12.  
  13. running = (sem <> 0)    
  14.  
  15. /* Use an Object REXX Queue to store note ons and offs */
  16. noteQ = .queue~new
  17. say "Initialized..."  
  18.  
  19. do while running
  20.    someInput = (Queued() <> 0) 
  21.    someChord = (noteQ~Items() <> 0) 
  22.  
  23.    do while someInput | someChord 
  24.       now = MoxGetSystemTime()  
  25.       if someInput 
  26.       then do 
  27.          pull timestamp status data1 data2
  28.  
  29.          /* Sent by MIDI-OX to signify end of program */
  30.          if timestamp = 'END_DATA' 
  31.          then do
  32.             running = 0
  33.             leave
  34.          end
  35.  
  36.          if status = 144 
  37.          then do /* only notes */
  38.             later = now + 400
  39.             event = .NoteEvent~New( later, 5, status, data1, data2 )
  40.             noteQ~Queue( event )
  41.          end
  42.       end
  43.  
  44.       if someChord 
  45.       then do
  46.          /* see if the queue head has expired yet */
  47.          event = noteQ~Peek()
  48.          if event~HasExpired( now ) 
  49.          then do
  50.             /* actually remove from Queue */
  51.             event = noteQ~Pull()
  52.          
  53.             ret = MoxOutputMidi( event~status, event~note, event~velocity )
  54.             if ret <> 0 
  55.             then do
  56.                 msg = "Error code: " || ret
  57.                call RxMessageBox msg, '', 'OK', 'STOP'  
  58.             end
  59.  
  60.             if event~Cycle() then
  61.                noteQ~Queue( event )
  62.          end
  63.       end
  64.  
  65.       someInput = (Queued() <> 0) 
  66.       someChord  = (noteQ~Items() <> 0) 
  67.    end
  68.  
  69.    if running 
  70.    then do
  71.       /* queue is empty: you could do other processing here */       
  72.       ret = SysWaitEventSem( sem )
  73.       if ret <> 0 
  74.       then do
  75.          running = .false
  76.          call RxMessageBox "Sem Code:" || ret, "err", 'OK', 'STOP'          
  77.       end
  78.    end
  79. end
  80.  
  81. Say "Exiting..."
  82. call SysDropFuncs 
  83. exit
  84.  
  85. /* ========================================================== */
  86.  
  87. ::class noteEvent subclass Object
  88. ::method Init
  89.   expose expire count status note velocity 
  90.   use arg expire, count, status, note, velocity 
  91.  
  92.   self~note = self~NextChordNote( self~note )
  93.   return
  94.  
  95. ::method expire   attribute
  96. ::method count    attribute 
  97. ::method status   attribute
  98. ::method note     attribute
  99. ::method velocity attribute
  100.  
  101. ::method HasExpired
  102.   use arg now
  103.   
  104.   if now > self~expire then
  105.      return 1
  106.   return 0
  107.  
  108. ::method Cycle
  109.   self~count = self~count - 1 /* one less to go */
  110.   if self~count > 2 
  111.   then do
  112.      self~expire = self~expire + 400
  113.      self~note = self~NextChordNote( self~note )
  114.      return 1
  115.   end
  116.   else if self~count > 0 
  117.   then do
  118.      self~expire = self~expire + 400
  119.      self~note = self~PrevChordNote( self~note )
  120.      return 1
  121.   end
  122.    
  123.   return 0
  124.  
  125. ::method NextChordNote
  126.   use arg lastNote
  127.   
  128.   /* use Key of C for simplicity */
  129.   remaind = (lastNote + 4) // 12
  130.   select  
  131.      when remaind = 1  then  nextnote = lastNote + 3
  132.      when remaind = 3  then  nextnote = lastNote + 3
  133.      when remaind = 6  then  nextnote = lastNote + 3
  134.      when remaind = 8  then  nextnote = lastNote + 3    
  135.      when remaind = 10 then  nextnote = lastNote + 3    
  136.      otherwise nextNote = lastNote + 4
  137.   end
  138.  
  139.   return nextNote
  140.  
  141. ::method PrevChordNote
  142.   use arg curNote
  143.   
  144.   /* use Key of C for simplicity */
  145.   remaind = curNote // 12
  146.   select  
  147.      when remaind = 1  then  prevnote = curNote - 4
  148.      when remaind = 4  then  prevnote = curNote - 4
  149.      when remaind = 6  then  prevnote = curNote - 4
  150.      when remaind = 9  then  prevnote = curNote - 4
  151.      when remaind = 11 then  prevnote = curNote - 4
  152.      otherwise prevNote = curNote - 3
  153.   end
  154.  
  155.   return prevNote
  156.